/*
 * @Date         : 2022-07-08 21:56:23
 * @LastEditors  : zu1662
 * @LastEditTime : 2024-05-24 15:11:41
 * @Description  : 邮件 service
 *
 * Copyright © 2022 by zu1662, All Rights Reserved.
 */
import nodemailer from 'nodemailer';
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { ConfigService } from '@nestjs/config';
import { Repository } from 'typeorm';
import { ISMTPListInfo, SmtpInfo } from './smtp.interface';
import { SMTPEntity } from './smtp.entity';

@Injectable()
export class SMTPService {
  private readonly smtpInfo: SmtpInfo;
  constructor(
    @InjectRepository(SMTPEntity)
    private readonly smtpRepository: Repository<SMTPEntity>,
    private readonly configService: ConfigService
  ) {
    const host = this.configService.get('smtp.host');
    const port = this.configService.get('smtp.port');
    const user = this.configService.get('smtp.user');
    const pass = this.configService.get('smtp.password');
    const fromEmail = this.configService.get('smtp.fromEmail');
    this.smtpInfo = {
      host,
      port,
      user,
      pass,
      fromEmail,
    };
  }

  /**
   * 获取所有邮件记录
   * @param queryParams
   */
  async findAll(queryParams: Record<string, any>): Promise<ISMTPListInfo> {
    const { skip, perPage, sort, availableSearch, search, filters } = queryParams;
    const query = this.smtpRepository
      .createQueryBuilder('smtp')
      .orderBy(`smtp.${sort.field}`, sort.sortType);
    // 如果 search 存在，则模糊搜索，filters 为精确到字段搜索
    if (search && typeof search === 'string') {
      const concatStr = availableSearch.reduce((total, cur, i) => {
        let str = total + 'smtp.' + cur;
        if (i < availableSearch.length - 1) str += ',';
        return str;
      }, '');
      query.andWhere(`CONCAT(${concatStr}) LIKE "%${search}%"`);
    } else if (filters && typeof filters === 'object') {
      availableSearch.forEach(key => {
        if (filters[key]) {
          query.andWhere(`smtp.${key} LIKE :${key}`).setParameter(`${key}`, `%${filters[key]}%`);
        }
      });
    }

    const totalData = await query.getCount();
    query.skip(skip);
    query.take(perPage);
    return {
      totalData,
      data: await query.getMany(),
    };
  }

  /**
   * 创建邮件记录
   * @param queryParams
   */
  async create(data: Partial<SMTPEntity>): Promise<SMTPEntity> {
    try {
      const sendMainInfo = await this.sendMail(data);
      const newComment = await this.smtpRepository.create(sendMainInfo);
      await this.smtpRepository.save(newComment);
      return newComment;
    } catch (e) {
      throw new HttpException('邮件发送失败', HttpStatus.BAD_REQUEST);
    }
  }

  /**
   * 获取指定邮件记录
   * @param id
   */
  async findById(id): Promise<SMTPEntity> {
    return this.smtpRepository.findOne({ where: { id } });
  }

  /**
   * 删除邮件记录
   * @param id
   */
  async deleteById(id) {
    const data = await this.smtpRepository.findOne({ where: { id } });
    return this.smtpRepository.remove(data);
  }

  /**
   * 发送邮件
   */
  async sendMail(message) {
    const config = {
      host: this.smtpInfo.host,
      port: this.smtpInfo.port || 465,
      username: this.smtpInfo.user,
      password: this.smtpInfo.pass,
      fromEmail: this.smtpInfo.fromEmail,
    };
    // const config = {
    //   host: 'smtp.189.cn',
    //   port: 465,
    //   username: 'huazite@189.cn',
    //   password: 'Huazite@189.com',
    //   fromEmail: 'huazite@189.cn'
    // }

    // 创建实例
    const transporter = await nodemailer.createTransport({
      host: config.host,
      port: config.port,
      secure: true, // ssl 为 true for 465, false for other ports
      auth: {
        user: config.username, // smtp 用户名
        pass: config.password, // smtp 密码
      },
    });

    // send mail with defined transport object
    const sendMainInfo = {
      from: message.from || config.username, // sender address
      to: message.to, // list of receivers
      subject: message.subject, // Subject line
      text: message.text, // plain text body
      html: message.html, // html body
    };
    await transporter.sendMail(sendMainInfo);
    return sendMainInfo;
  }
}
